home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / sre_parse.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  19KB  |  799 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import sys
  5. from sre_constants import *
  6.  
  7. def set(seq):
  8.     s = { }
  9.     for elem in seq:
  10.         s[elem] = 1
  11.     
  12.     return s
  13.  
  14. SPECIAL_CHARS = '.\\[{()*+?^$|'
  15. REPEAT_CHARS = '*+?{'
  16. DIGITS = set('0123456789')
  17. OCTDIGITS = set('01234567')
  18. HEXDIGITS = set('0123456789abcdefABCDEF')
  19. WHITESPACE = set(' \t\n\r\x0b\x0c')
  20. ESCAPES = {
  21.     '\\a': (LITERAL, ord('\x07')),
  22.     '\\b': (LITERAL, ord('\x08')),
  23.     '\\f': (LITERAL, ord('\x0c')),
  24.     '\\n': (LITERAL, ord('\n')),
  25.     '\\r': (LITERAL, ord('\r')),
  26.     '\\t': (LITERAL, ord('\t')),
  27.     '\\v': (LITERAL, ord('\x0b')),
  28.     '\\\\': (LITERAL, ord('\\')) }
  29. CATEGORIES = {
  30.     '\\A': (AT, AT_BEGINNING_STRING),
  31.     '\\b': (AT, AT_BOUNDARY),
  32.     '\\B': (AT, AT_NON_BOUNDARY),
  33.     '\\d': (IN, [
  34.         (CATEGORY, CATEGORY_DIGIT)]),
  35.     '\\D': (IN, [
  36.         (CATEGORY, CATEGORY_NOT_DIGIT)]),
  37.     '\\s': (IN, [
  38.         (CATEGORY, CATEGORY_SPACE)]),
  39.     '\\S': (IN, [
  40.         (CATEGORY, CATEGORY_NOT_SPACE)]),
  41.     '\\w': (IN, [
  42.         (CATEGORY, CATEGORY_WORD)]),
  43.     '\\W': (IN, [
  44.         (CATEGORY, CATEGORY_NOT_WORD)]),
  45.     '\\Z': (AT, AT_END_STRING) }
  46. FLAGS = {
  47.     'i': SRE_FLAG_IGNORECASE,
  48.     'L': SRE_FLAG_LOCALE,
  49.     'm': SRE_FLAG_MULTILINE,
  50.     's': SRE_FLAG_DOTALL,
  51.     'x': SRE_FLAG_VERBOSE,
  52.     't': SRE_FLAG_TEMPLATE,
  53.     'u': SRE_FLAG_UNICODE }
  54.  
  55. class Pattern:
  56.     
  57.     def __init__(self):
  58.         self.flags = 0
  59.         self.open = []
  60.         self.groups = 1
  61.         self.groupdict = { }
  62.  
  63.     
  64.     def opengroup(self, name = None):
  65.         gid = self.groups
  66.         self.groups = gid + 1
  67.         if name is not None:
  68.             ogid = self.groupdict.get(name, None)
  69.             if ogid is not None:
  70.                 raise error, 'redefinition of group name %s as group %d; was group %d' % (repr(name), gid, ogid)
  71.             
  72.             self.groupdict[name] = gid
  73.         
  74.         self.open.append(gid)
  75.         return gid
  76.  
  77.     
  78.     def closegroup(self, gid):
  79.         self.open.remove(gid)
  80.  
  81.     
  82.     def checkgroup(self, gid):
  83.         if gid < self.groups:
  84.             pass
  85.         return gid not in self.open
  86.  
  87.  
  88.  
  89. class SubPattern:
  90.     
  91.     def __init__(self, pattern, data = None):
  92.         self.pattern = pattern
  93.         if data is None:
  94.             data = []
  95.         
  96.         self.data = data
  97.         self.width = None
  98.  
  99.     
  100.     def dump(self, level = 0):
  101.         nl = 1
  102.         seqtypes = (type(()), type([]))
  103.         for op, av in self.data:
  104.             print level * '  ' + op,
  105.             nl = 0
  106.             if op == 'in':
  107.                 print 
  108.                 nl = 1
  109.                 for op, a in av:
  110.                     print (level + 1) * '  ' + op, a
  111.                 
  112.             elif op == 'branch':
  113.                 print 
  114.                 nl = 1
  115.                 i = 0
  116.                 for a in av[1]:
  117.                     if i > 0:
  118.                         print level * '  ' + 'or'
  119.                     
  120.                     a.dump(level + 1)
  121.                     nl = 1
  122.                     i = i + 1
  123.                 
  124.             elif type(av) in seqtypes:
  125.                 for a in av:
  126.                     if isinstance(a, SubPattern):
  127.                         if not nl:
  128.                             print 
  129.                         
  130.                         a.dump(level + 1)
  131.                         nl = 1
  132.                         continue
  133.                     print a,
  134.                     nl = 0
  135.                 
  136.             else:
  137.                 print av,
  138.                 nl = 0
  139.             if not nl:
  140.                 print 
  141.                 continue
  142.         
  143.  
  144.     
  145.     def __repr__(self):
  146.         return repr(self.data)
  147.  
  148.     
  149.     def __len__(self):
  150.         return len(self.data)
  151.  
  152.     
  153.     def __delitem__(self, index):
  154.         del self.data[index]
  155.  
  156.     
  157.     def __getitem__(self, index):
  158.         return self.data[index]
  159.  
  160.     
  161.     def __setitem__(self, index, code):
  162.         self.data[index] = code
  163.  
  164.     
  165.     def __getslice__(self, start, stop):
  166.         return SubPattern(self.pattern, self.data[start:stop])
  167.  
  168.     
  169.     def insert(self, index, code):
  170.         self.data.insert(index, code)
  171.  
  172.     
  173.     def append(self, code):
  174.         self.data.append(code)
  175.  
  176.     
  177.     def getwidth(self):
  178.         if self.width:
  179.             return self.width
  180.         
  181.         lo = hi = 0x0L
  182.         UNITCODES = (ANY, RANGE, IN, LITERAL, NOT_LITERAL, CATEGORY)
  183.         REPEATCODES = (MIN_REPEAT, MAX_REPEAT)
  184.         for op, av in self.data:
  185.             if op is BRANCH:
  186.                 i = sys.maxint
  187.                 j = 0
  188.                 for av in av[1]:
  189.                     (l, h) = av.getwidth()
  190.                     i = min(i, l)
  191.                     j = max(j, h)
  192.                 
  193.                 lo = lo + i
  194.                 hi = hi + j
  195.                 continue
  196.             if op is CALL:
  197.                 (i, j) = av.getwidth()
  198.                 lo = lo + i
  199.                 hi = hi + j
  200.                 continue
  201.             if op is SUBPATTERN:
  202.                 (i, j) = av[1].getwidth()
  203.                 lo = lo + i
  204.                 hi = hi + j
  205.                 continue
  206.             if op in REPEATCODES:
  207.                 (i, j) = av[2].getwidth()
  208.                 lo = lo + long(i) * av[0]
  209.                 hi = hi + long(j) * av[1]
  210.                 continue
  211.             if op in UNITCODES:
  212.                 lo = lo + 1
  213.                 hi = hi + 1
  214.                 continue
  215.             if op == SUCCESS:
  216.                 break
  217.                 continue
  218.         
  219.         self.width = (int(min(lo, sys.maxint)), int(min(hi, sys.maxint)))
  220.         return self.width
  221.  
  222.  
  223.  
  224. class Tokenizer:
  225.     
  226.     def __init__(self, string):
  227.         self.string = string
  228.         self.index = 0
  229.         self._Tokenizer__next()
  230.  
  231.     
  232.     def __next(self):
  233.         if self.index >= len(self.string):
  234.             self.next = None
  235.             return None
  236.         
  237.         char = self.string[self.index]
  238.         if char[0] == '\\':
  239.             
  240.             try:
  241.                 c = self.string[self.index + 1]
  242.             except IndexError:
  243.                 raise error, 'bogus escape (end of line)'
  244.  
  245.             char = char + c
  246.         
  247.         self.index = self.index + len(char)
  248.         self.next = char
  249.  
  250.     
  251.     def match(self, char, skip = 1):
  252.         if char == self.next:
  253.             if skip:
  254.                 self._Tokenizer__next()
  255.             
  256.             return 1
  257.         
  258.         return 0
  259.  
  260.     
  261.     def get(self):
  262.         this = self.next
  263.         self._Tokenizer__next()
  264.         return this
  265.  
  266.     
  267.     def tell(self):
  268.         return (self.index, self.next)
  269.  
  270.     
  271.     def seek(self, index):
  272.         (self.index, self.next) = index
  273.  
  274.  
  275.  
  276. def isident(char):
  277.     return None if char <= char else None if char <= char else char == '_'
  278.  
  279.  
  280. def isdigit(char):
  281.     return None if char <= char else char <= '9'
  282.  
  283.  
  284. def isname(name):
  285.     if not isident(name[0]):
  286.         return False
  287.     
  288.     for char in name[1:]:
  289.         if not isident(char) and not isdigit(char):
  290.             return False
  291.             continue
  292.     
  293.     return True
  294.  
  295.  
  296. def _class_escape(source, escape):
  297.     code = ESCAPES.get(escape)
  298.     if code:
  299.         return code
  300.     
  301.     code = CATEGORIES.get(escape)
  302.     if code:
  303.         return code
  304.     
  305.     
  306.     try:
  307.         c = escape[1:2]
  308.         if c == 'x':
  309.             while source.next in HEXDIGITS and len(escape) < 4:
  310.                 escape = escape + source.get()
  311.             escape = escape[2:]
  312.             if len(escape) != 2:
  313.                 raise error, 'bogus escape: %s' % repr('\\' + escape)
  314.             
  315.             return (LITERAL, int(escape, 16) & 255)
  316.         elif c in OCTDIGITS:
  317.             while source.next in OCTDIGITS and len(escape) < 4:
  318.                 escape = escape + source.get()
  319.             escape = escape[1:]
  320.             return (LITERAL, int(escape, 8) & 255)
  321.         elif c in DIGITS:
  322.             raise error, 'bogus escape: %s' % repr(escape)
  323.         
  324.         if len(escape) == 2:
  325.             return (LITERAL, ord(escape[1]))
  326.     except ValueError:
  327.         pass
  328.  
  329.     raise error, 'bogus escape: %s' % repr(escape)
  330.  
  331.  
  332. def _escape(source, escape, state):
  333.     code = CATEGORIES.get(escape)
  334.     if code:
  335.         return code
  336.     
  337.     code = ESCAPES.get(escape)
  338.     if code:
  339.         return code
  340.     
  341.     
  342.     try:
  343.         c = escape[1:2]
  344.         if c == 'x':
  345.             while source.next in HEXDIGITS and len(escape) < 4:
  346.                 escape = escape + source.get()
  347.             if len(escape) != 4:
  348.                 raise ValueError
  349.             
  350.             return (LITERAL, int(escape[2:], 16) & 255)
  351.         elif c == '0':
  352.             while source.next in OCTDIGITS and len(escape) < 4:
  353.                 escape = escape + source.get()
  354.             return (LITERAL, int(escape[1:], 8) & 255)
  355.         elif c in DIGITS:
  356.             if source.next in DIGITS:
  357.                 escape = escape + source.get()
  358.                 if escape[1] in OCTDIGITS and escape[2] in OCTDIGITS and source.next in OCTDIGITS:
  359.                     escape = escape + source.get()
  360.                     return (LITERAL, int(escape[1:], 8) & 255)
  361.                 
  362.             
  363.             group = int(escape[1:])
  364.             if group < state.groups:
  365.                 if not state.checkgroup(group):
  366.                     raise error, 'cannot refer to open group'
  367.                 
  368.                 return (GROUPREF, group)
  369.             
  370.             raise ValueError
  371.         
  372.         if len(escape) == 2:
  373.             return (LITERAL, ord(escape[1]))
  374.     except ValueError:
  375.         pass
  376.  
  377.     raise error, 'bogus escape: %s' % repr(escape)
  378.  
  379.  
  380. def _parse_sub(source, state, nested = 1):
  381.     items = []
  382.     itemsappend = items.append
  383.     sourcematch = source.match
  384.     while None:
  385.         if sourcematch('|'):
  386.             continue
  387.         
  388.         if not nested:
  389.             break
  390.         
  391.         if not (source.next) or sourcematch(')', 0):
  392.             break
  393.             continue
  394.         raise error, 'pattern not properly closed'
  395.         continue
  396.         if len(items) == 1:
  397.             return items[0]
  398.         
  399.     subpattern = SubPattern(state)
  400.     subpatternappend = subpattern.append
  401.     while None:
  402.         prefix = None
  403.         for item in items:
  404.             if not item:
  405.                 break
  406.             
  407.             if prefix is None:
  408.                 prefix = item[0]
  409.                 continue
  410.             if item[0] != prefix:
  411.                 break
  412.                 continue
  413.         else:
  414.             for item in items:
  415.                 del item[0]
  416.             
  417.         break
  418.         continue
  419.         for item in items:
  420.             if len(item) != 1 or item[0][0] != LITERAL:
  421.                 break
  422.                 continue
  423.         else:
  424.             set = []
  425.             setappend = set.append
  426.             for item in items:
  427.                 setappend(item[0])
  428.             
  429.             return subpattern
  430.     subpattern.append((BRANCH, (None, items)))
  431.     return subpattern
  432.  
  433.  
  434. def _parse_sub_cond(source, state, condgroup):
  435.     item_yes = _parse(source, state)
  436.     if source.match('|'):
  437.         item_no = _parse(source, state)
  438.         if source.match('|'):
  439.             raise error, 'conditional backref with more than two branches'
  440.         
  441.     else:
  442.         item_no = None
  443.     if source.next and not source.match(')', 0):
  444.         raise error, 'pattern not properly closed'
  445.     
  446.     subpattern = SubPattern(state)
  447.     subpattern.append((GROUPREF_EXISTS, (condgroup, item_yes, item_no)))
  448.     return subpattern
  449.  
  450. _PATTERNENDERS = set('|)')
  451. _ASSERTCHARS = set('=!<')
  452. _LOOKBEHINDASSERTCHARS = set('=!')
  453. _REPEATCODES = set([
  454.     MIN_REPEAT,
  455.     MAX_REPEAT])
  456.  
  457. def _parse(source, state):
  458.     subpattern = SubPattern(state)
  459.     subpatternappend = subpattern.append
  460.     sourceget = source.get
  461.     sourcematch = source.match
  462.     _len = len
  463.     PATTERNENDERS = _PATTERNENDERS
  464.     ASSERTCHARS = _ASSERTCHARS
  465.     LOOKBEHINDASSERTCHARS = _LOOKBEHINDASSERTCHARS
  466.     REPEATCODES = _REPEATCODES
  467.     while source.next in PATTERNENDERS:
  468.         break
  469.     this = sourceget()
  470.     if this is None:
  471.         break
  472.     
  473.     if state.flags & SRE_FLAG_VERBOSE:
  474.         if this in WHITESPACE:
  475.             continue
  476.         
  477.         if this == '#':
  478.             while None:
  479.                 this = sourceget()
  480.                 if this in (None, '\n'):
  481.                     break
  482.                     continue
  483.                 continue
  484.                 continue
  485.         this == '#'
  486.     
  487.     None if this and this[0] not in SPECIAL_CHARS else sourcematch('?')
  488.     if this == '.':
  489.         subpatternappend((ANY, None))
  490.         continue
  491.     if this == '(':
  492.         group = 1
  493.         name = None
  494.         condgroup = None
  495.         if sourcematch('?'):
  496.             group = 0
  497.             if sourcematch('P'):
  498.                 if sourcematch('<'):
  499.                     name = ''
  500.                     while None:
  501.                         char = sourceget()
  502.                         if char is None:
  503.                             raise error, 'unterminated name'
  504.                         
  505.                         if char == '>':
  506.                             break
  507.                         
  508.                         name = name + char
  509.                         continue
  510.                         group = 1
  511.                         if not isname(name):
  512.                             raise error, 'bad character in group name'
  513.                         
  514.                 isname(name)
  515.                 if sourcematch('='):
  516.                     name = ''
  517.                     while None:
  518.                         char = sourceget()
  519.                         if char is None:
  520.                             raise error, 'unterminated name'
  521.                         
  522.                         if char == ')':
  523.                             break
  524.                         
  525.                         name = name + char
  526.                         continue
  527.                         if not isname(name):
  528.                             raise error, 'bad character in group name'
  529.                         
  530.                     gid = state.groupdict.get(name)
  531.                     if gid is None:
  532.                         raise error, 'unknown group name'
  533.                     
  534.                     subpatternappend((GROUPREF, gid))
  535.                     continue
  536.                 else:
  537.                     char = sourceget()
  538.                     if char is None:
  539.                         raise error, 'unexpected end of pattern'
  540.                     
  541.                     raise error, 'unknown specifier: ?P%s' % char
  542.             elif sourcematch(':'):
  543.                 group = 2
  544.             elif sourcematch('#'):
  545.                 while source.next is None or source.next == ')':
  546.                     break
  547.                 sourcematch('?')
  548.                 sourceget()
  549.                 continue
  550.                 if not sourcematch(')'):
  551.                     raise error, 'unbalanced parenthesis'
  552.                     continue
  553.                 continue
  554.             elif source.next in ASSERTCHARS:
  555.                 char = sourceget()
  556.                 dir = 1
  557.                 if char == '<':
  558.                     if source.next not in LOOKBEHINDASSERTCHARS:
  559.                         raise error, 'syntax error'
  560.                     
  561.                     dir = -1
  562.                     char = sourceget()
  563.                 
  564.                 p = _parse_sub(source, state)
  565.                 if not sourcematch(')'):
  566.                     raise error, 'unbalanced parenthesis'
  567.                 
  568.                 if char == '=':
  569.                     subpatternappend((ASSERT, (dir, p)))
  570.                     continue
  571.                 subpatternappend((ASSERT_NOT, (dir, p)))
  572.                 continue
  573.             elif sourcematch('('):
  574.                 condname = ''
  575.                 while None:
  576.                     char = sourceget()
  577.                     if char is None:
  578.                         raise error, 'unterminated name'
  579.                     
  580.                     if char == ')':
  581.                         break
  582.                     
  583.                     condname = condname + char
  584.                     continue
  585.                     group = 2
  586.                     if isname(condname):
  587.                         condgroup = state.groupdict.get(condname)
  588.                         if condgroup is None:
  589.                             raise error, 'unknown group name'
  590.                         
  591.                     else:
  592.                         
  593.                         try:
  594.                             condgroup = int(condname)
  595.                         except ValueError:
  596.                             raise error, 'bad character in group name'
  597.                         except:
  598.                             None<EXCEPTION MATCH>ValueError
  599.                         
  600.  
  601.                         None<EXCEPTION MATCH>ValueError
  602.                         if source.next not in FLAGS:
  603.                             raise error, 'unexpected end of pattern'
  604.                         
  605.             while source.next in FLAGS:
  606.                 state.flags = state.flags | FLAGS[sourceget()]
  607.         
  608.         if group:
  609.             if group == 2:
  610.                 group = None
  611.             else:
  612.                 group = state.opengroup(name)
  613.             if condgroup:
  614.                 p = _parse_sub_cond(source, state, condgroup)
  615.             else:
  616.                 p = _parse_sub(source, state)
  617.             if not sourcematch(')'):
  618.                 raise error, 'unbalanced parenthesis'
  619.             
  620.             if group is not None:
  621.                 state.closegroup(group)
  622.             
  623.             subpatternappend((SUBPATTERN, (group, p)))
  624.         else:
  625.             while None:
  626.                 char = sourceget()
  627.                 if char is None:
  628.                     raise error, 'unexpected end of pattern'
  629.                 
  630.                 if char == ')':
  631.                     break
  632.                 
  633.                 raise error, 'unknown extension'
  634.                 continue
  635.                 continue
  636.                 if this == '^':
  637.                     subpatternappend((AT, AT_BEGINNING))
  638.                     continue
  639.                 if this == '$':
  640.                     subpattern.append((AT, AT_END))
  641.                     continue
  642.                 if this and this[0] == '\\':
  643.                     code = _escape(source, this, state)
  644.                     subpatternappend(code)
  645.                     continue
  646.                 raise error, 'parser error'
  647.                 continue
  648.                 return subpattern
  649.  
  650.  
  651. def parse(str, flags = 0, pattern = None):
  652.     source = Tokenizer(str)
  653.     if pattern is None:
  654.         pattern = Pattern()
  655.     
  656.     pattern.flags = flags
  657.     pattern.str = str
  658.     p = _parse_sub(source, pattern, 0)
  659.     tail = source.get()
  660.     if tail == ')':
  661.         raise error, 'unbalanced parenthesis'
  662.     elif tail:
  663.         raise error, 'bogus characters at end of regular expression'
  664.     
  665.     if flags & SRE_FLAG_DEBUG:
  666.         p.dump()
  667.     
  668.     if not (flags & SRE_FLAG_VERBOSE) and p.pattern.flags & SRE_FLAG_VERBOSE:
  669.         return parse(str, p.pattern.flags)
  670.     
  671.     return p
  672.  
  673.  
  674. def parse_template(source, pattern):
  675.     s = Tokenizer(source)
  676.     sget = s.get
  677.     p = []
  678.     a = p.append
  679.     
  680.     def literal(literal, p = p, pappend = a):
  681.         if p and p[-1][0] is LITERAL:
  682.             p[-1] = (LITERAL, p[-1][1] + literal)
  683.         else:
  684.             pappend((LITERAL, literal))
  685.  
  686.     sep = source[:0]
  687.     if type(sep) is type(''):
  688.         makechar = chr
  689.     else:
  690.         makechar = unichr
  691.     while None:
  692.         this = sget()
  693.         if this is None:
  694.             break
  695.         
  696.         if this and this[0] == '\\':
  697.             c = this[1:2]
  698.             if c == 'g':
  699.                 name = ''
  700.                 if s.match('<'):
  701.                     while None:
  702.                         char = sget()
  703.                         if char is None:
  704.                             raise error, 'unterminated group name'
  705.                         
  706.                         if char == '>':
  707.                             break
  708.                         
  709.                         name = name + char
  710.                         continue
  711.                 s.match('<')
  712.                 if not name:
  713.                     raise error, 'bad group name'
  714.                 
  715.                 
  716.                 try:
  717.                     index = int(name)
  718.                     if index < 0:
  719.                         raise error, 'negative group number'
  720.                 except ValueError:
  721.                     if not isname(name):
  722.                         raise error, 'bad character in group name'
  723.                     
  724.                     
  725.                     try:
  726.                         index = pattern.groupindex[name]
  727.                     except KeyError:
  728.                         raise IndexError, 'unknown group name'
  729.                     except:
  730.                         None<EXCEPTION MATCH>KeyError
  731.                     
  732.  
  733.                     None<EXCEPTION MATCH>KeyError
  734.  
  735.                 a((MARK, index))
  736.             elif c == '0':
  737.                 if s.next in OCTDIGITS:
  738.                     this = this + sget()
  739.                     if s.next in OCTDIGITS:
  740.                         this = this + sget()
  741.                     
  742.                 
  743.                 literal(makechar(int(this[1:], 8) & 255))
  744.             elif c in DIGITS:
  745.                 isoctal = False
  746.                 if s.next in DIGITS:
  747.                     this = this + sget()
  748.                     if c in OCTDIGITS and this[2] in OCTDIGITS and s.next in OCTDIGITS:
  749.                         this = this + sget()
  750.                         isoctal = True
  751.                         literal(makechar(int(this[1:], 8) & 255))
  752.                     
  753.                 
  754.                 if not isoctal:
  755.                     a((MARK, int(this[1:])))
  756.                 
  757.             else:
  758.                 
  759.                 try:
  760.                     this = makechar(ESCAPES[this][1])
  761.                 except KeyError:
  762.                     pass
  763.  
  764.                 literal(this)
  765.         literal(this)
  766.         continue
  767.         i = 0
  768.         groups = []
  769.         groupsappend = groups.append
  770.         literals = [
  771.             None] * len(p)
  772.         for c, s in p:
  773.             if c is MARK:
  774.                 groupsappend((i, s))
  775.             else:
  776.                 literals[i] = s
  777.             i = i + 1
  778.         
  779.     return (groups, literals)
  780.  
  781.  
  782. def expand_template(template, match):
  783.     g = match.group
  784.     sep = match.string[:0]
  785.     (groups, literals) = template
  786.     literals = literals[:]
  787.     
  788.     try:
  789.         for index, group in groups:
  790.             literals[index] = s = g(group)
  791.             if s is None:
  792.                 raise error, 'unmatched group'
  793.                 continue
  794.     except IndexError:
  795.         raise error, 'invalid group reference'
  796.  
  797.     return sep.join(literals)
  798.  
  799.